package cn.zebra.dev.admin.module.security.service;

import cn.zebra.dev.admin.module.security.entity.AdminDetailsEntity;
import cn.zebra.dev.base.module.admin.entity.BaseAdmin;
import cn.zebra.dev.base.module.admin.service.BaseAdminService;
import cn.zebra.dev.common.constant.SysConstant;
import cn.zebra.dev.common.utils.StrUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 用户详细信息
 *
 * @author runnable@sina.cn
 */
@Slf4j
@Service
public class AdminDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private BaseAdminService adminService;

    /**
     * 获取后台用户信息
     *
     * @param account 后台用户账号
     */
    @Override
    public UserDetails loadUserByUsername(String account) {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String key = SysConstant.SECURITY_ADMIN_ACCOUNT + account;
        String json = valueOperations.get(key);
        if (StrUtils.isNotBlank(json)) {
            return JSON.parseObject(json, AdminDetailsEntity.class);
        }
        BaseAdmin admin = adminService.findAdminByAccount(account);
        AdminDetailsEntity detailsEntity = new AdminDetailsEntity(admin);
        saveRedis(key, valueOperations, detailsEntity);
        return detailsEntity;
    }

    /**
     * 异步存放至redis
     *
     * @param key             键
     * @param valueOperations redisOperations
     * @param detailsEntity   用户对象
     */
    @Async
    void saveRedis(String key, ValueOperations<String, String> valueOperations, AdminDetailsEntity detailsEntity) {
        valueOperations.set(key, JSON.toJSONString(detailsEntity), 7, TimeUnit.DAYS);
    }

}
